package com.minisoft.jd.seckill;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author JueSu
 * @description: TODO
 * @date 2021/11/29 22:24
 */
@Slf4j
public class Killer {

    static String[] cartLines = new String[]{
            "Accept: application/json, text/plain, */*",
            "Accept-Encoding: gzip, deflate, br",
            "Accept-Language: zh-CN,zh;q=0.9",
            "Cache-Control: no-cache",
            "Connection: keep-alive",
            "Content-Length: 368",
            "Content-Type: application/x-www-form-urlencoded",
            "Cookie: user-key=673fdf6a-f79a-4ea3-9e26-7812f2f7c63c; cart-main=xx; cd=1; ipLocation=%u5e7f%u4e1c; __jdu=16379073960431184175253; areaId=19; PCSYCityID=CN_440000_440400_440402; shshshfpb=huiRjZ4Kn9FAlmsNwppsA%20A%3D%3D; shshshfpa=c4e9c702-4e8f-6a4f-9e09-a6819cd21ba9-1627119916; pinId=EvE-50nGwH3ZTlS-EiSWPA; pin=juesuchen; unick=%E5%8D%97%E5%B8%8Cnancy%E6%BD%98; _tp=uJs1qGio5uDIOiZ1tFsPbw%3D%3D; _pst=juesuchen; ipLoc-djd=19-1657-3001-0.137909159; __jdv=122270672|baidu|-|organic|not set|1637942612740; TrackID=11xPOuE0HRh9gJfSFPPCRcxXE4TQSoj8aRBPaqeTXe7CzLxXPGnBWhrMPS59qC3-JxFJkIuk96lrx-cMZYHhgqupx8qAhemQ8Eqf3izwihBY; ceshi3.com=103; cn=40; __jda=122270672.16379073960431184175253.1637907396.1637998248.1638021354.11; __jdc=122270672; shshshfp=fccd6560609afcbfacad9a900053c0e1; token=9d60fc41f1d7f702149ad4e6bc8a8b71,3,910011; __tk=kyCIZbRxRjKHZkRFj1OnBkRVq1pHZl9ckxPOZzRSod33TcR4TxPwpCfFTyC3qckiSkk3AD5n,3,910011; thor=A6B163847E03FD546F3BF4599CDE88FE4A358FDC733691ABBCF366BFA27F5546894F658E79C20FCE05E3ECE636B19FFAAC06303FC335CCA2521EA5B2AA6C113DF2320DED25F1C76ACA22707B1FA09849FCBB7B2D4AEB1667B4F5D9FADEBAAC7A8B7FF92E59156C4F0CF260E652397ED8F54D2EA44DB8CC30783BDAC8381404665CF54C05AD709D19A2E6F76F0C74CF44; __jdb=122270672.10.16379073960431184175253|11.1638021354; shshshsID=88058708b5ad6e76c48fd928e2919408_7_1638022516875; 3AB9D23F7A4B3C9B=OMIJOWZ3QL6G537C6AMOJEXLTWBG2DLOPREHKBDLDV52NWIWOF54VDTQ5HQM76LS4EHTL4LQS72AT3AD5VBRPN47CI",
            "Host: api.m.jd.com",
            "Origin: https://cart.jd.com",
            "Pragma: no-cache",
            "Referer: https://cart.jd.com/",
            "sec-ch-ua: \"Chromium\";v=\"92\", \" Not A;Brand\";v=\"99\", \"Google Chrome\";v=\"92\"",
            "sec-ch-ua-mobile: ?0",
            "Sec-Fetch-Dest: empty",
            "Sec-Fetch-Mode: cors",
            "Sec-Fetch-Site: same-site",
            "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
    };
    static String[] submitLines = new String[]{
            "Accept: application/json, text/javascript, */*; q=0.01",
            "Accept-Encoding: gzip, deflate, br",
            "Accept-Language: zh-CN,zh;q=0.9",
            "Cache-Control: no-cache",
            "Connection: keep-alive",
            "Content-Length: 424",
            "Content-Type: application/x-www-form-urlencoded",
            "Cookie: user-key=673fdf6a-f79a-4ea3-9e26-7812f2f7c63c; cart-main=xx; cd=1; ipLocation=%u5e7f%u4e1c; __jdu=16379073960431184175253; areaId=19; PCSYCityID=CN_440000_440400_440402; shshshfpb=huiRjZ4Kn9FAlmsNwppsA%20A%3D%3D; shshshfpa=c4e9c702-4e8f-6a4f-9e09-a6819cd21ba9-1627119916; pinId=EvE-50nGwH3ZTlS-EiSWPA; pin=juesuchen; unick=%E5%8D%97%E5%B8%8Cnancy%E6%BD%98; _tp=uJs1qGio5uDIOiZ1tFsPbw%3D%3D; _pst=juesuchen; ipLoc-djd=19-1657-3001-0.137909159; __jdv=122270672|baidu|-|organic|not set|1637942612740; TrackID=11xPOuE0HRh9gJfSFPPCRcxXE4TQSoj8aRBPaqeTXe7CzLxXPGnBWhrMPS59qC3-JxFJkIuk96lrx-cMZYHhgqupx8qAhemQ8Eqf3izwihBY; ceshi3.com=103; cn=40; __jda=122270672.16379073960431184175253.1637907396.1637998248.1638021354.11; __jdc=122270672; shshshfp=fccd6560609afcbfacad9a900053c0e1; token=9d60fc41f1d7f702149ad4e6bc8a8b71,3,910011; __tk=kyCIZbRxRjKHZkRFj1OnBkRVq1pHZl9ckxPOZzRSod33TcR4TxPwpCfFTyC3qckiSkk3AD5n,3,910011; thor=A6B163847E03FD546F3BF4599CDE88FE4A358FDC733691ABBCF366BFA27F5546894F658E79C20FCE05E3ECE636B19FFAAC06303FC335CCA2521EA5B2AA6C113DF2320DED25F1C76ACA22707B1FA09849FCBB7B2D4AEB1667B4F5D9FADEBAAC7A8B7FF92E59156C4F0CF260E652397ED8F54D2EA44DB8CC30783BDAC8381404665CF54C05AD709D19A2E6F76F0C74CF44; __jdb=122270672.10.16379073960431184175253|11.1638021354; shshshsID=88058708b5ad6e76c48fd928e2919408_7_1638022516875; 3AB9D23F7A4B3C9B=OMIJOWZ3QL6G537C6AMOJEXLTWBG2DLOPREHKBDLDV52NWIWOF54VDTQ5HQM76LS4EHTL4LQS72AT3AD5VBRPN47CI",
            "Host: trade.jd.com",
            "Origin: https://trade.jd.com",
            "Pragma: no-cache",
            "Referer: https://trade.jd.com/shopping/order/getOrderInfo.action",
            "sec-ch-ua: \"Chromium\";v=\"92\", \" Not A;Brand\";v=\"99\", \"Google Chrome\";v=\"92\"",
            "sec-ch-ua-mobile: ?0",
            "Sec-Fetch-Dest: empty",
            "Sec-Fetch-Mode: cors",
            "Sec-Fetch-Site: same-origin",
            "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
            "X-Requested-With: XMLHttpRequest"
    };

    String cookieStr = "__jdc=122270672; __jda=122270672.16385315732231875663622.1638531573.1638531573.1638531573.1; __jdv=122270672|direct|-|none|-|1638531573224; __jdu=16385315732231875663622; shshshfp=753409dfebcdeeb0790ed8790389066f; shshshfpa=00494d8e-3dd9-67db-beb6-07a71aa20a73-1638531574; shshshfpb=yPV4CACQOe+vXN0I23T5Z3g; TARGET_UNIT=bjcenter; ipLoc-djd=19-1657-0-0; areaId=19; wlfstk_smdl=cfzh4ep86pj9zgtgn02agtm988vkxo3a; 3AB9D23F7A4B3C9B=Q4FVL6B2VHDD62QTWWOZ6LIXXI2PZAGG2EOO65ZHN72ORHCYBN2Q2BF7DQMB6XMLPMLEYAL7MPRWGFUOVL3LBWM66I; TrackID=1IKVreVAqNeV37t0ek4dpzg3rBFFvOHlogBz8_nOvisMckfUSdnaBs170ZbJp_j21eOXg9wpCL-oQSMAj0M_tuEeSxGQMu8fvg8SIdcDNEs4; thor=A6B163847E03FD546F3BF4599CDE88FE61FDC016C3048A4C8FA3BD124FD7126979A9BC7126960A106BCCCD370EAA5D8471CA57B203DFF7B5BD52DB252081292803172D2892B84D4B129447BBA2121499B651E9628D72C177E221CA444A047D1650F07B43626BE86431F8E5385C59A5481767155E53BC933B29B33C97766C1193992CEA039E21BC2CD3090DCA5D347E8F; pinId=EvE-50nGwH3ZTlS-EiSWPA; pin=juesuchen; unick=%E5%8D%97%E5%B8%8Cnancy%E6%BD%98; ceshi3.com=103; _tp=uJs1qGio5uDIOiZ1tFsPbw%3D%3D; _pst=juesuchen; cn=52; __jdb=122270672.5.16385315732231875663622|1.1638531573; shshshsID=8eab52ed44da525819318f35405b43c3_2_1638531591933";

    Map<String, String> headers = getHeaderMap(0);
    Map<String, String> submitHeaders = getHeaderMap(1);
    private static Map<Integer,Integer> sTypeMap = new HashMap<>();

    public final static String TO_EMAIL = "571964946@139.com";

    static {
        sTypeMap.put(16,13);
        sTypeMap.put(11,11);
        sTypeMap.put(4,4);
    }

    private String userKey = "";//好像为空也没问题
    private String nickName = "";//cookie不为空时，赋值
    private String retryOrderInterval;
    /**
     * 可通过环境变量 SLEEP_TIME 指定
     */
    private Integer sleepTime = 100;

    /**
     * 登录是否使用发邮件
     */
    private boolean loginWithEmail= false;

    public Killer(String profile, String loginWithEmail, String retryOrderInterval) {
        this.profile = profile;
        this.loginWithEmail = Boolean.valueOf(loginWithEmail);
        nickName = profile;
        this.retryOrderInterval = retryOrderInterval;
        sleepTime = Convert.toInt(System.getenv("SLEEP_TIME"), 100);
        log("sleepTime = {},loginWithEmail = {}",sleepTime,loginWithEmail);

        File cookieFile = new File(getCookieFile());
        String cookie = null;
        if (cookieFile.exists()) {
            cookie = FileUtil.readUtf8String(cookieFile);
        }
        setCookie(cookie);
//        log("max price : {}",price);
    }

    volatile int price = 1024;

    final int MAX_RETRY = 16;

    private volatile int patternIdx = 0;
    private volatile boolean isCollectLog = false;

    //要购买的商品id
    private String pid;

    private String skuId;

    private String profile;

    private static String[] schedulingPattern = new String[]{
            "58 59 5,7,9,11,13,15,17,19,21,23 * * *",
            "59 59 5,7,9,11,13,15,17,19,21,23 * * *",
            "0 0 0,6,8,10,12,14,16,18,20,22 * * *"};

    private volatile String checkBody;
    private volatile String checkName;
    private static volatile int CART_LOOP = 10;
    private volatile List<String> collectedLogs = new ArrayList<>();

    public void setCookie(String cookie) {
        if (StrUtil.isNotBlank(cookie)) {
            nickName = "";
            String[] cookieStrs = cookie.split("; ");
            for (String cookieStr : cookieStrs) {
                String[] cookieArray = cookieStr.split("=");
                if ("unick".equals(cookieArray[0])) {
                    nickName = cookieArray[1];
                    break;
                }
            }
        }
        headers.put("Cookie",cookie);
        submitHeaders.put("Cookie",cookie);
    }

    private String getCookieFile() {
        return "cookies/" + profile + ".txt";
    }

    /**
     * 立刻执行
     */
    public void exec(String pid,boolean checkLogin) {
        this.pid = pid;
        if (checkLogin) {
            checkIsLogin();
        }
        getCheckBody();
        if (checkBody != null && addToCart() < MAX_RETRY) {
            submitOrder();
        }

        if (checkBody == null && yuYuePid != null) {
            doYuYueOrder();
        }
        this.pid = null;
    }

    private void doYuYueOrder() {
        int idx = 0;
        boolean isSuccess = false;

        while (!isSuccess && idx++ < MAX_RETRY) {
            log("try to do YuYueOrder:{}",idx);
            geteAction(yuYuePid);
            //检查购物车是否有加入到此产品
            isSuccess = checkPidInCart(yuYuePid);
            if (isSuccess) {//成功加入购物车后
                exec(yuYuePid,false);
            }
        }
    }

    /**
     * 定时任务执行
     * @throws Exception
     */
    public void start() {

        checkIsLogin();
        checkJdTime();
        getCheckBody();

        //每20分钟心跳
        CronUtil.schedule("20 0/20 * * * *", new Task() {
            public void execute() {
                checkIsLogin();
                getCheckBody();
            }
        });

        //最后时间进行获取
        CronUtil.schedule("45 59 5,7,9,11,13,15,17,19,21,23 * * *", new Task() {
            public void execute() {
                getCheckBody();
            }
        });

        //抢购定时
        CronUtil.schedule(schedulingPattern[patternIdx], new Task() {
            public void execute() {
                collectedLogs.clear();
                isCollectLog = true;
                if (checkBody != null && addToCart() < MAX_RETRY) {
                    for (int i = 0;i< 5;i++) {
                        log("submitOrder: i = {}", i);
                        if (submitOrder()) {
                            break;
                        }
                        if (StrUtil.isNotBlank(retryOrderInterval)) {
                            ThreadUtil.sleep(Long.parseLong(retryOrderInterval));
                        }
                    }
                }
                //如果是预约列表的商品，需要加购物车，并下单
                if (checkBody == null && yuYuePid != null) {
                    doYuYueOrder();
                }
                isCollectLog = false;
            }
        });
    }

    public String getCheckedInfo() {
        return StrUtil.format("【{}】{}",nickName,checkName);
    }

    public String getOrderInfo() {

        Map<String, String> headerMap = getHeaderMap(0);
        headerMap.put("Host","order.jd.com");
        headerMap.put("Referer","https://order.jd.com/center/list.action?s=1");
        headerMap.put("Cookie",headers.get("Cookie"));
        String body = HttpUtil.createGet("https://order.jd.com/center/list.action").headerMap(headerMap, true).execute().body();

        Document doc = Jsoup.parse(body);
        String dealtime = doc.selectFirst("table.order-tb  span.dealtime").text();
        String name = doc.selectFirst("table.order-tb  div.p-name a").text();
        String amount = doc.selectFirst("table.order-tb  div.amount").text();
        LocalDateTime localDateTime = LocalDateTime.now().minusMinutes(10);
        LocalDateTime dateTime = DateUtil.parseLocalDateTime(dealtime);
        if (dateTime.isAfter(localDateTime)) {
            //如果是5分钟内的订单，则显示
            return StrUtil.format("【{}】 {} {}",nickName,name,amount);
        }
        return "";
    }

    public void delOrderInCancel() {

        Map<String, String> headerMap = getHeaderMap(0);
        headerMap.put("Host","order.jd.com");
        headerMap.put("Referer","https://order.jd.com/center/list.action?s=1");
        headerMap.put("Cookie",headers.get("Cookie"));
        String body = HttpUtil.createGet("https://order.jd.com/center/list.action?search=0&d=2&s=-1").headerMap(headerMap, true).execute().body();
        Document doc = Jsoup.parse(body);
        Elements delElements = doc.select("a.order-del");
        while (CollUtil.isNotEmpty(delElements)) {
            for (Element delElement : delElements) {
                String _orderid = delElement.attr("_orderid");
                String _passkey = delElement.attr("_passkey");
                String url = StrUtil.format("https://order.jd.com/lazy/recycleOrder.action?orderId={}&PassKey={}&callback=jQuery7633670&_={}",_orderid,_passkey,System.currentTimeMillis());
                body = HttpUtil.createGet(url).headerMap(headerMap, true).execute().body();
                ThreadUtil.sleep(500);
                Console.log("delOrderInCancel:{}",body);
            }
            body = HttpUtil.createGet("https://order.jd.com/center/list.action?search=0&d=2&s=-1").headerMap(headerMap, true).execute().body();
            doc = Jsoup.parse(body);
            delElements = doc.select("a.order-del");
        }
    }

    public void delOrderInRecycle() {
        Map<String, String> headerMap = getHeaderMap(0);
        headerMap.put("Host","order.jd.com");
        headerMap.put("Referer","https://order.jd.com/center/recycle.action?d=1");
        headerMap.put("Cookie",headers.get("Cookie"));
        String body = HttpUtil.createGet("https://order.jd.com/center/recycle.action?d=2").headerMap(headerMap, true).execute().body();
        Document doc = Jsoup.parse(body);
        Elements delElements = doc.select("a.order-del");
        while (CollUtil.isNotEmpty(delElements)) {
            for (Element delElement : delElements) {
                String _orderid = delElement.attr("_orderid");
                String _passkey = delElement.attr("_passkey");
                String url = StrUtil.format("https://order.jd.com/lazy/deleteOrder.action?orderId={}&PassKey={}&callback=jQuery7633670&_={}",_orderid,_passkey,System.currentTimeMillis());
                body = HttpUtil.createGet(url).headerMap(headerMap, true).execute().body();
                ThreadUtil.sleep(500);
                Console.log("delOrderInRecycle:{}",body);

            }
            body = HttpUtil.createGet("https://order.jd.com/center/recycle.action?d=1").headerMap(headerMap, true).execute().body();
            doc = Jsoup.parse(body);
            delElements = doc.select("a.order-del");
        }
    }
    public String getOrderLog() {
        StringBuilder sb = new StringBuilder();
        collectedLogs.forEach(item -> sb.append("<div>").append(item).append("</div>"));
        return sb.toString();
    }

    private void checkJdTime() {
        JSONObject jdTime = JSONUtil.parseObj(HttpUtil.get("https://api.m.jd.com/client.action?functionId=queryMaterialProducts&client=wh5"));
        long diff = jdTime.getLong("currentTime2") - System.currentTimeMillis();
        if (diff < 1000) {
            patternIdx = 1;
        } else {
            patternIdx = 0;
        }
        log("diff(jd-local) = {} ,pattern = {}",diff,schedulingPattern[patternIdx]);
    }

    public boolean submitOrder() {
        String url = "https://trade.jd.com/shopping/order/getOrderInfo.action";
        HttpUtil.createGet(url).headerMap(submitHeaders, true).execute().body();
//        log("getOrderInfo====>");

//        url = "https://trade.jd.com/shopping/dynamic/coupon/getCoupons.action";
//        Map<String, Object> map = new HashMap<>();
//        map.put("presaleStockSign",1);
//        HttpResponse response = HttpUtil.createPost(url).headerMap(submitHeaders, true).form(map).execute();
//        HttpCookie jsessionid = response.getCookie("JSESSIONID");
//        String submitCookie = submitHeaders.get("Cookie")+"; "+jsessionid.toString();
//        submitHeaders.put("Cookie",submitCookie);

        url = "https://trade.jd.com/shopping/order/submitOrder.action?&presaleStockSign=1";
        Map<String, Object> formMap = getSubmitFormMap(null);
        String body = HttpUtil.createPost(url).headerMap(submitHeaders, true).form(formMap).execute().body();
        JSONObject bodyJson = JSONUtil.parseObj(body);
//        log("order result: {}",body);
        Boolean success = bodyJson.getBool("success");
        String message = StrUtil.blankToDefault(bodyJson.getStr("message"),bodyJson.getStr("errorMessage"));
        log("submitOrder message:{},success:{}",message,success);
        if(!success && message.contains("立即抢购")) {
            //需要重回页面进行订购的
            return buyNow();
        }
        return success;
    }

    /**
     * 立即抢购
     */
    public boolean buyNow() {
        skuId = "637437";
        log("进行立即抢购模式,skuId={}",skuId);
        Map<String, String> headerMap = getHeaderMap(0);
        headerMap.put("Host","marathon.jd.com");
//        headerMap.put("Referer","https://order.jd.com/center/recycle.action?d=1");
        headerMap.put("Cookie",headers.get("Cookie"));
        String url = "https://marathon.jd.com/seckill/seckill.action?skuId="+skuId+"&num=1&rid=1641778781";
        HttpUtil.createGet(url).headerMap(headerMap, true).execute().body();

        url = "https://marathon.jd.com/seckillnew/orderService/pc/init.action";
        Map<String, Object> formMap = new HashMap<>();
        formMap.put("sku",skuId);
        formMap.put("num","1");
        String initBody = HttpUtil.createPost(url).headerMap(headerMap, true).form(formMap).execute().body();
        JSONObject initJson = JSONUtil.parseObj(initBody);
        url = "https://marathon.jd.com/seckillnew/orderService/pc/submitOrder.action?skuId="+skuId;
        formMap = getSubmitFormMap(initJson);
        String body = HttpUtil.createPost(url).headerMap(headerMap, true).form(formMap).execute().body();
        JSONObject bodyJson = JSONUtil.parseObj(body);
        Boolean success = bodyJson.getBool("success");
        String message = StrUtil.blankToDefault(bodyJson.getStr("message"),bodyJson.getStr("errorMessage"));
        log("submitOrder message:{},success:{}",message,success);
        return success;
    }

    private static Map<String, Object> getSubmitFormMap(JSONObject initJson) {
        Map<String,Object> subData = new HashMap<>();
        if (initJson == null) {
            subData.put("overseaPurchaseCookies", "");
            subData.put("vendorRemarks", "[]");
            subData.put("submitOrderParam.sopNotPutInvoice", "false");
            subData.put("submitOrderParam.trackID", "TestTrackId");
            subData.put("presaleStockSign", "1");
            subData.put("submitOrderParam.ignorePriceChange", "0");
            subData.put("submitOrderParam.btSupport", "0");
            subData.put("submitOrderParam.eid", "OMIJOWZ3QL6G537C6AMOJEXLTWBG2DLOPREHKBDLDV52NWIWOF54VDTQ5HQM76LS4EHTL4LQS72AT3AD5VBRPN47CI");
            subData.put("submitOrderParam.fp", "82bb31d970a370095d2352f68798d8c7");
            subData.put("submitOrderParam.jxj", "1");
        } else {

            subData.put("skuId", initJson.getByPath("seckillSkuVO.skuId"));
            subData.put("num", "1");
            subData.put("addressId", initJson.getByPath("address.id"));
            subData.put("name", initJson.getByPath("address.name"));
            subData.put("provinceId", initJson.getByPath("address.provinceId"));
            subData.put("cityId", initJson.getByPath("address.cityId"));
            subData.put("countyId", initJson.getByPath("address.countyId"));
            subData.put("townId", initJson.getByPath("address.townId"));
            subData.put("provinceName", initJson.getByPath("address.provinceName"));
            subData.put("cityName", initJson.getByPath("address.cityName"));
            subData.put("countyName",initJson.getByPath("address.countyName"));
            subData.put("addressDetail", initJson.getByPath("address.addressDetail"));
            subData.put("mobile", initJson.getByPath("address.mobile"));
            subData.put("mobileKey", initJson.getByPath("address.mobileKey"));
            subData.put("invoiceTitle", "4");
            subData.put("invoiceContent", "1");
            subData.put("invoicePhone", subData.get("mobile"));
            subData.put("invoicePhoneKey", subData.get("mobileKey"));
            subData.put("invoice", "true");
            subData.put("codTimeType", "3");
            subData.put("paymentType", "4");
            subData.put("overseas", "0");
            subData.put("eid", "OMIJOWZ3QL6G537C6AMOJEXLTWBG2DLOPREHKBDLDV52NWIWOF54VDTQ5HQM76LS4EHTL4LQS72AT3AD5VBRPN47CI");
            subData.put("fp", "089b2f019a085104e18ef91854438513");
            subData.put("token", initJson.getByPath("token"));
//            subData.put("sk", "YVHD3HWY8Z1IMU4AZU6DN7EX");
        }
        return subData;
    }

    public void checkIsLogin() {
        Map<String, Object> formMap = new HashMap<>();
        formMap.put("presaleStockSign", "1");
        String url = "https://trade.jd.com/shopping/dynamic/order/checkPlusQualification.action";
        String body = HttpUtil.createPost(url).headerMap(submitHeaders, true).form(formMap).execute().body();
//        log("{} checkIsLogin = {}",body);
        //如果没有登录，则弹出登录码，有效期是3分钟
        if (StrUtil.isBlank(submitHeaders.get("Cookie")) || !NumberUtil.isNumber(body)) {
            File file = new File(getCookieFile());
            try {
                String newCookie = null;
                String iamgeName = StrUtil.blankToDefault(nickName,profile);
                while (newCookie == null) {//没有成功登录，则继续
                    newCookie = Login.login(iamgeName+".png", cookieStr,loginWithEmail);
                }
                //登录成功
                setCookie(newCookie);
                //写回到文件
                FileUtil.writeUtf8String(newCookie,file);
            } catch (Exception e) {
                log.error("checkIsLogin error.",e);
            }
        }
    }

    public void getCheckBody() {
        Map<String, Object> formMap = getFormMap(0);
        String url = "https://api.m.jd.com/api";
        String body = HttpUtil.createPost(url).headerMap(headers, true).form(formMap).execute().body();
//        log(body);
        checkBody = getCheckCartBody(body);
        //没有在购物车找到，则在预约列表看看
        if (checkBody == null) {
            yuYuePid = getFromYuyueList();
        }
        log(checkName);
//        log("checkBody = {}",checkBody);
    }

    public int addToCart() {
        String url = "https://api.m.jd.com/api";
        Map<String, Object> formMap = getFormMap(1);
        formMap.put("body",checkBody);
        int idx = 0;
        boolean doFlag = true;
        while (doFlag && idx++ < MAX_RETRY) {
            String body = HttpUtil.createPost(url).headerMap(headers, true).form(formMap).execute().body();
            try {
                JSONObject bodyJson = JSONUtil.parseObj(body);
                int wareNum = bodyJson.getByPath("resultData.cartInfo.checkedWareNum", Integer.class);
                Double cartPrice = bodyJson.getByPath("resultData.cartInfo.Price", Double.class);
//            log(body);
                log("{}.addToCart message:{},success:{},checkedWareNum:{},cartPrice:{}",
                        idx, bodyJson.getStr("message"),
                        bodyJson.getBool("success"),wareNum,cartPrice);

                doFlag = wareNum == 0 || cartPrice > price;
                if (doFlag) {
                    ThreadUtil.sleep(sleepTime);
                }
            } catch (Exception e){
                log("addToCart error, {} ", body);
                if (idx > 5) {
                    return MAX_RETRY;
                }
            }
        }
        return idx;
    }


    public void toYuyue(String pid) {
        Map<String, String> headerMap = getHeaderMap(0);
        headerMap.put("Host","item-soa.jd.com");
        headerMap.put("Referer","https://item.yiyaojd.com/");
        headerMap.put("Cookie",headers.get("Cookie"));
        String body = HttpUtil.createGet("https://item-soa.jd.com/getWareBusiness?skuId="+pid).headerMap(headerMap, true).execute().body();;
        JSONObject json = JSONUtil.parseObj(body);
        JSONObject yuyueInfo = json.getJSONObject("yuyueInfo");
        if (yuyueInfo != null) {
            //yushou.jd.com/toYuyue.action?sku=100015280610&key=4d9b8b36b54acc6ad93a5e3cc1dc873b
            Integer shopId = (Integer) json.getByPath("shopInfo.shop.shopId");
            String url = StrUtil.format("https:{}&shopId={}&isPlusLimit=0",yuyueInfo.getStr("url"),shopId);
            headerMap = getHeaderMap(1);
            headerMap.put("Host","yushou.jd.com");
            headerMap.put("Cookie",headers.get("Cookie"));
            body = HttpUtil.createGet(url).headerMap(headerMap, true).execute().body();
            System.out.println(body);
            log("预约商品{} {}",pid,body.contains("预约成功，已获得抢购资格"));
        }
    }

    private boolean checkPidInCart(String pid) {
        Map<String, Object> formMap = getFormMap(0);
        String url = "https://api.m.jd.com/api";
        String body = HttpUtil.createPost(url).headerMap(headers, true).form(formMap).execute().body();
        JSONArray vendors = (JSONArray) JSONUtil.parseObj(body).
                getByPath("resultData.cartInfo.vendors");
        int len = 5;
        for (int k = 0;k < len; k++) {
            JSONObject vendor = (JSONObject) vendors.get(k);
            JSONArray sorted = vendor.getJSONArray("sorted");
            for (int i = 0; i < sorted.size(); i++) {
                JSONObject itemJson = (JSONObject) sorted.get(i);
                Integer itemType = itemJson.getInt("itemType");

                if (itemType == 1) {
                    JSONObject skuItem = itemJson.getJSONObject("item");
                    String skuId = skuItem.getStr("Id");
                    if (StrUtil.equals(pid, skuId)) {
                        return true;
                    }
                } else {
                    itemJson = itemJson.getJSONObject("item");
                    if (itemType == 4) {
                        String ybPackId = itemJson.getStr("vskuId");
                        if (StrUtil.equals(pid, ybPackId)) {
                            return true;
                        }
                    } else {
                        JSONArray items = itemJson.getJSONArray("items");
                        for (int j = 0; j < items.size(); j++) {
                            JSONObject skuItem = (JSONObject) items.get(j);
                            itemJson = skuItem.getJSONObject("item");
                            String skuId = itemJson.getStr("Id");
                            if (StrUtil.equals(pid, skuId)) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * 获取选择购物车的参数
     * @param body
     * @return
     */
    private String getCheckCartBody(String body) {
        JSONArray vendors = (JSONArray) JSONUtil.parseObj(body).
                getByPath("resultData.cartInfo.vendors");
        if (vendors == null) {
            log(body);
            return null;
        }
        int len = NumberUtil.min(vendors.size(), CART_LOOP);
        for (int k = 0;k < len; k++) {
            JSONObject vendor = (JSONObject) vendors.get(k);
            JSONArray sorted = vendor.getJSONArray("sorted");
            for (int i = 0; i < sorted.size(); i++) {
                JSONObject itemJson = (JSONObject) sorted.get(i);
                Integer itemType = itemJson.getInt("itemType");

                if (itemType == 1) {
                    JSONObject skuItem = itemJson.getJSONObject("item");
                    if (nextMs(skuItem,pid)){
                        checkName = skuItem.getStr("Name");
                        skuId = skuItem.getStr("Id");
                        String skuUuid = skuItem.getStr("skuUuid");
                        return StrUtil.format(checkBodys[0],skuId,skuUuid,userKey);
                    }
                } else{
                    itemJson = itemJson.getJSONObject("item");
                    long packId = itemJson.getLong("Id");
                    Integer sType = itemJson.getInt("SType");
                    if (itemType == 4) {
                        Integer yuyueLimitTime = itemJson.getInt("yuyueLimitTime");
                        String ybPackId = itemJson.getStr("vskuId");
                        if (StrUtil.equals(pid,ybPackId) || (yuyueLimitTime != null && yuyueLimitTime < 3600 * 2)) {
                            if (!sTypeMap.containsKey(sType)) {
                                log("无法找到sType:" + sType);
                                break;
                            }
                            checkName = itemJson.getStr("Name");
                            JSONArray items = itemJson.getJSONArray("items");
                            JSONArray theSkus = getSkus(items);
                            return StrUtil.format(checkBodys[2],sTypeMap.get(sType),packId,ybPackId,theSkus.toString(),userKey);
                        }
                    } else {
                        JSONArray items = itemJson.getJSONArray("items");
                        for (int j = 0; j < items.size(); j++) {
                            JSONObject skuItem = (JSONObject) items.get(j);
                            itemJson = skuItem.getJSONObject("item");
                            if (nextMs(itemJson,pid)){
                                skuId = itemJson.getStr("Id");
                                String skuUuid = itemJson.getStr("skuUuid");
                                if (!sTypeMap.containsKey(sType)) {
                                    log("无法找到sType:" + sType);
                                    break;
                                }
                                checkName = itemJson.getStr("Name");
                                return StrUtil.format(checkBodys[1],sTypeMap.get(sType),packId,skuId,skuUuid,userKey);
                            }
                        }
                    }

                }
            }
        }
        checkName = "暂无抢购商品加入购物车";
        return null;
    }

    private JSONArray getSkus(JSONArray items) {
        JSONArray theSkus = new JSONArray();
        for (int j = 0; j < items.size(); j++) {
            JSONObject skuItem = (JSONObject) items.get(j);
            JSONObject itemJson = skuItem.getJSONObject("item");
            JSONObject skuJson = new JSONObject();
            skuJson.set("Id",itemJson.getStr("Id"))
                    .set("num",itemJson.getStr("Num"))
                    .set("useUuid",itemJson.getBool("useUuid"))
                    .set("skuUuid",itemJson.getStr("skuUuid"));
            theSkus.add(skuJson);
        }
        return theSkus;
    }

    private static boolean nextMs(JSONObject skuItem, String pid) {
        Integer secKillStartCountdown = skuItem.getInt("secKillStartCountdown");
        //如果秒杀倒计时少于2小时,则说明是即将的商品
        String skuId = skuItem.getStr("Id");
        if (StrUtil.isBlank(pid)) {
            return secKillStartCountdown != null && secKillStartCountdown < 2 * 3600;
        }
        return StrUtil.equals(pid,skuId);
    }

    static String[] checkBodys = new String[]{
            "{\"operations\":[{\"TheSkus\":[{\"Id\":\"{}\",\"num\":1,\"skuUuid\":\"{}\",\"useUuid\":false}]}],\"serInfo\":{\"area\":\"19_1657_3001_0\",\"user-key\":\"{}\"}}",
            "{\"operations\":[{\"carttype\":\"5\",\"ThePacks\":[{\"num\":1,\"sType\":{},\"Id\":{},\"TheSkus\":[{\"num\":1,\"Id\":\"{}\",\"skuUuid\":\"{}\",\"useUuid\":false}]}]}],\"serInfo\":{\"area\":\"19_1657_3001_0\",\"user-key\":\"{}\"}}",
            "{\"operations\":[{\"carttype\":\"5\",\"ThePacks\":[{\"num\":1,\"sType\":{},\"Id\":{},\"ybPackId\":{},\"TheSkus\":{}}]}],\"serInfo\":{\"area\":\"19_1657_3001_0\",\"user-key\":\"{}\"}}"
    };

    public void geteAction(String pid) {
        Map<String, String> headerMap = getHeaderMap(0);
        headerMap.put("Host","cart.jd.com");
        headerMap.put("Referer","https://item.jd.com/");
        headerMap.put("Cookie",headers.get("Cookie"));
        String body = HttpUtil.createGet("https://cart.jd.com/gate.action?pcount=1&ptype=1&pid="+pid).headerMap(headerMap, true).execute().body();
        Console.log("geteAction result : {}",body);
    }

    private String yuYuePid;

    public String getFromYuyueList() {
        Map<String, String> headerMap = getHeaderMap(0);
        headerMap.put("Host","yushou.jd.com");
        headerMap.put("Cookie",headers.get("Cookie"));
        String body = HttpUtil.createGet("https://yushou.jd.com/member/qualificationList.action").headerMap(headerMap, true).execute().body();

        Document doc = Jsoup.parse(body);
        Elements titleElements = doc.select("div.prod-title a");
        Elements stimeElements = doc.select("input[id$=_buystime]");
        LocalDateTime localDateTime = LocalDateTime.now().plusHours(2);
        for (int i = 0 ;i < stimeElements.size();i++) {
            Element element = stimeElements.get(i);
            String stime = element.val();
            if (StrUtil.isBlank(stime)) {
                continue;
            }
            LocalDateTime startTime = DateUtil.parseLocalDateTime(stime);
            //如果是两小时内，说明是即将预约的
            if (startTime.isBefore(localDateTime)) {
                checkName = titleElements.get(i).text() + "【预约】";
                return element.id().split("_")[0];
            }
        }
        return null;
    }

    public static Map<String, String> getHeaderMap(int i) {
        String[] headerLines = i == 0 ? cartLines : submitLines;
        Map<String, String> headers = new HashMap<>();
        for (String line : headerLines) {
            if (!line.startsWith("Content-Length")) {
                String[] split = line.split(": ");
                headers.put(split[0], split[1]);
            }
        }
        return headers;
    }

    private static Map<String, Object> getFormMap(int i) {
        Map<String,Object> form = new HashMap<>();
        if (i == 0) {
            form.put("functionId","pcCart_jc_getCurrentCart");
            form.put("appid","JDC_mall_cart");
            form.put("loginType","3");
            form.put("body","{\"serInfo\":{\"area\":\"19_1657_3001_0\",\"user-key\":\"673fdf6a-f79a-4ea3-9e26-7812f2f7c63c\"},\"cartExt\":{\"specialId\":1}}");
        } else {
            form.put("functionId","pcCart_jc_cartCheckSingle");
            form.put("appid","JDC_mall_cart");
            form.put("body","{\"operations\":[{\"carttype\":\"5\",\"ThePacks\":[{\"num\":1,\"sType\":11,\"Id\":200185610063,\"TheSkus\":[{\"num\":1,\"Id\":\"100018420680\",\"skuUuid\":\"F2h3C1L1021384480271114240\",\"useUuid\":false}]}]}],\"serInfo\":{\"area\":\"19_1657_3001_0\",\"user-key\":\"673fdf6a-f79a-4ea3-9e26-7812f2f7c63c\"}}");
        }
        return form;
    }

    private void log(String msg,Object... args) {
        log.info("【{}】 {}",nickName,StrUtil.format(msg,args));
        if (isCollectLog) {
            collectedLogs.add(StrUtil.format("【{}】 {} {}", nickName, LocalTime.now(),StrUtil.format(msg,args)));
        }
    }

}
